package asteroids.model.programs.statement;
 
import java.util.ArrayList;
import java.util.List;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
 
import be.kuleuven.cs.som.annotate.*;
import asteroids.model.programs.expression.*;
import asteroids.model.programs.type.*;
import asteroids.model.*;
 
public class ForEach extends S {
 
        private asteroids.model.programs.parsing.ProgramFactory.ForeachType type;
        private String variableName;
        private S body;
        private Set<SpaceObject> list;
       
        public ForEach(int line, int column, asteroids.model.programs.parsing.ProgramFactory.ForeachType type, String variableName, S body) {
                super(line, column);
                this.type = type;
                this.variableName = variableName;
                this.body = body;
                list = new HashSet<SpaceObject>();
        }
 
        @Override
        public boolean isForEach(){
                return true;
        }
       
        @Basic
        public S getBody(){
                return body;
        }
       
        @Basic
        public String getVariableName(){
                return variableName;
        }
 
        //does nothing: forEach has no actual execution, if just gives back his body
    @Override
    public void execute(T type) {
    }
   
    //
public void setVariableToEntity(List<VariableExpression> list, Entity e){
        for(VariableExpression v : list){//link the variableName with the spaceObject
                        if(v.getName().equals(getVariableName())){
                                v.setValue(e);
                                break;
                        }
                }
        }
 
        @Override
        public boolean hasSteps() {
                return body.hasSteps();
        }
       
        public Set<SpaceObject> getList(World world){
                list.clear();
                switch(type) {
                        case SHIP:
                                list.addAll(world.getShips());
                                return list;
                        case ASTEROID:
                                list.addAll(world.getAsteroids());
                                return list;
                        case BULLET:
                                list.addAll(world.getBullets());
                                return list;
                        case ANY:
                                list.addAll(world.getBullets());
                                list.addAll(world.getAsteroids());
                                list.addAll(world.getShips());
                                return list;
                }
                return null;
        }
       
        public void setExecuted(boolean b){
                body.setExecuted(b);
                super.setExecuted(b);
        }
       
        @Override
        public ArrayList<E> getExpressions() {
                return body.getExpressions();
        }
       
        @Override
        public ArrayList<VariableExpression> getVariableExpressions(){
                return body.getVariableExpressions();
        }
        
        public boolean hasAction(){
        	return body.hasAction();
        }
	
	public String typecheck(Map<String, T> globals){
		T type = globals.get(getVariableName());
		String bTypeCheck = getBody().typecheck(globals);
		if(body.hasAction())
			bTypeCheck = bTypeCheck + "Action in ForEach loop at line " + getLine() + ", column " + getColumn() +".\n";
		if(type == null || type.getClass() != Entity.class)
			return "Typecast error at line " + getLine() + ", column " + getColumn() + ".\n" + bTypeCheck;
		else 
			return bTypeCheck;
	}
}
